#ifndef __BUFMNGR_H__
#define __BUFMNGR_H__

#include <windows.h>

#define SAFEREL(x) {if(x) (x)->Release();(x)=NULL;}
#define SAFEDEL(x) {if(x) delete (x);(x)=NULL;}
#define SAFEDELA(x) {if(x) delete[] (x);(x)=NULL;}

#define FO_CRYPT(rand_crypt_key) \
(((((((rand_crypt_key >> 11) ^ rand_crypt_key) & 0xFF3A58AD) << 7) \
^ (rand_crypt_key >> 11) ^ rand_crypt_key) & 0xFFFFDF8C) << 15) \
^ ((((rand_crypt_key >> 11) ^ rand_crypt_key) & 0xFF3A58AD) << 7) \
^ (rand_crypt_key >> 11) ^ rand_crypt_key \

class BufferManager {
private:
	bool error;
	CRITICAL_SECTION crit_section;
	char* data;
	DWORD len;
	DWORD pos;
	DWORD end_pos;
	DWORD read_pos;
	bool is_encrypted;
	int key_index;
	DWORD keys_table[50];

public:
	BufferManager();
	BufferManager(DWORD alen);
	~BufferManager();

	void Dump(void);
	DWORD GetLen(void);
	DWORD GetEndPos(void);
	DWORD GetReadPos(void);
	char* GetData(void);
	char* GetCurData(void);
	void Cut(DWORD size);
	bool Reset(void);
	void GrowBuf(DWORD size);
	bool IsEmpty(void);
	bool IsError(void);
	bool IsValidMsg(DWORD msgid);
	void Lock(void);
	void Unlock(void);
	void LockReset(void);
	void Pop(char *buffer, DWORD size);
	void Push(char *buffer, char* unknown, DWORD size);
	void Push(char *buffer, DWORD size, bool mode);
	void CopyBuf(char const *buffer_src, char* buffer_dest, char const* unknown, DWORD key, DWORD size);
	DWORD EncryptKey(int offset);
	int MoveReadPos(int offset);
	bool NeedProcess(void);
	void Refresh(void);
	bool SeekValidMsg(void);
	void SetEncryptKey(DWORD);
	DWORD SetEndPos(DWORD endpos);
	DWORD SkipMsg(DWORD msgid);

	BufferManager &operator<<(bool i);
	BufferManager &operator>>(bool &i);

	BufferManager &operator<<(char i);
	BufferManager &operator>>(char &i);

	BufferManager &operator<<(short i);
	BufferManager &operator>>(short &i);

	BufferManager &operator<<(int i);
	BufferManager &operator>>(int &i);

	BufferManager &operator<<(unsigned char i);
	BufferManager &operator>>(unsigned char &i);

	BufferManager &operator<<(unsigned short i);
	BufferManager &operator>>(unsigned short &i);

	BufferManager &operator<<(unsigned int i);
	BufferManager &operator>>(unsigned int &i);

	BufferManager &operator<<(DWORD i);
	BufferManager &operator>>(DWORD &i);

	BufferManager &operator=(BufferManager const &i);
};

#endif //__BUFMNGR_H__
